package com.goods.shop.service.librarys;

import cn.hutool.http.HtmlUtil;

import com.goods.shop.model.finals.BaiduFinal;
import com.goods.shop.model.librarys.SearchResultModel;
import com.goods.shop.service.AbstractService;
import com.goods.shop.util.HttpUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

/**
 * 根据关键词，文化,研究院,章程根据这几个关键词来同时搜索，查找一条记录中同时存在这几条记录的值
 */
@Service
public class SearchKeysServiceImpl extends AbstractService implements SearchKeysService{
    int perPageSize=10;
    int totalPage=40;//总共查询20页// TODO
    private  Pattern titlePattern=Pattern.compile("<h3 class=\" t\">(.*?)</h3>");
    public Map<String,String> generateHeader(){
        Map<String,String> headers=new HashMap<>();
        headers.put("Connection", "keep-alive");
        headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        headers.put("Accept-Encoding", "gzip, deflate, br");
        headers.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7");
        headers.put("User-Agent",
                "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36");
        headers.put("Cookie","BAIDUID=5548F404790F0EF9089B625E84331679:FG=1; BIDUPSID=5548F404790F0EF9089B625E84331679; PSTM=1546951184; MSA_WH=375_812; H_WISE_SIDS=142066_143857_143389_142761_142206_143879_141876_141746_143162_143422_142514_139177_142919_142779_131247_141261_138165_138883_141942_127969_140065_143368_140593_134046_143059_141808_137911_140350_138425_141008_143471_143923_143276_141930_131423_144005_107313_138595_139882_143478_143045_142912_143548_142278_110085; BD_UPN=12314453; BDUSS=lnV2cxLTdKd1ZTaTlEMXl1MG5VN29-bXRscWJONUZibDU1a1Y3V1EyVXRSVmRmRVFBQUFBJCQAAAAAAAAAAAEAAABKHFYAd2p4XzU4OTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC24L18tuC9fQn; BDUSS_BFESS=lnV2cxLTdKd1ZTaTlEMXl1MG5VN29-bXRscWJONUZibDU1a1Y3V1EyVXRSVmRmRVFBQUFBJCQAAAAAAAAAAAEAAABKHFYAd2p4XzU4OTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC24L18tuC9fQn; delPer=0; BD_CK_SAM=1; PSINO=2; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_HOME=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; H_PS_645EC=5396V0XI%2BWalwev4gXOY%2FeWucFkYDHQCH%2BoUt5bw9y3c6QB6l3UiHF1IAPwk%2FUPlYf2y; H_PS_PSSID=1468_32539_31253_32046_32116_32091_32482; BDSVRTM=0");
        headers.put("Host", "www.baidu.com");
        headers.put("Sec-Fetch-Dest", "document");
        headers.put("Sec-Fetch-Mode", "navigate");
        headers.put("Sec-Fetch-Site", "none");
        headers.put("Sec-Fetch-User", "?1");
        headers.put("Upgrade-Insecure-Requests", "1");
        return headers;
    }
    @Override
    public List<String> getKeys() {
        List<String> keys=new ArrayList<>();
//        keys.add("公共图书馆,乡村振兴");
//        keys.add("基层图书馆,乡村振兴");
//        keys.add("乡村图书馆,乡村振兴");
//        keys.add("农家书屋,乡村振兴");
//        keys.add("公共文化服务,乡村振兴");
//        keys.add("图书馆,乡村振兴");
//        keys.add("图书馆,乡村文化振兴");
//        keys.add("图书馆,文化扶贫");
//        keys.add("图书馆,农村");
//        keys.add("图书馆,农民");
//        keys.add("图书馆,留守");
        keys.add("图书馆,留守");
        return keys;
    }

    /**
     * 根据图书馆和关键词 迪卡尔积 来拼成多条记录，每个图书錧都和关键词来拼起来
     * @return
     */
    public List<String> getKeysFromLibrarys(Map<String,String> librarys,List<String> keys) {
        List<String> resultsKeys=new ArrayList<>();
        for(Map.Entry<String,String> library:librarys.entrySet()){
            for(String key:keys){
                resultsKeys.add(library.getKey()+","+key);
            }
        }
        return resultsKeys;
    }
    @Override
    public Map<String,String> getLibrarys(String file) {
        Map<String,String> citys=new HashMap<>();
        BufferedReader reader=null;
        try {
            reader=new BufferedReader(new InputStreamReader(new FileInputStream(new File(file)),"UTF-8"));
            String line=null;
            while((line=reader.readLine())!=null){
                line=line.trim();
                if(line.endsWith("图书馆"))
                {
                    citys.put(line,"");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(reader!=null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.info("end...."+citys.size());
        return citys;
    }

    private boolean checkCityExist(String title,String keys){
        String[] keyArrays=keys.split(",");
        for(String key:keyArrays){
            if(title.indexOf(key)==-1){
                return false;
            }
        }
        return true;
    }
    private List<SearchResultModel> analyseOne(String keys){
        List<SearchResultModel> datas=new ArrayList<SearchResultModel>();
        List<SearchResultModel> resultList=new ArrayList<>();
        String[] keyArrays=keys.split(",");
        StringBuilder wd=new StringBuilder("");
        int index=0;
        for(String key:keyArrays){
            if(index==keyArrays.length-1)
            {
                wd.append(key);
            }else{
                wd.append(key).append("%20");
            }
            index++;
        }

        Map<String,String> headers=this.generateHeader();
        Map<String,Object> params=new HashMap<>();
        params.put("wd",wd.toString());

        for(int page=0;page<totalPage;page++){
            int pn=page*perPageSize;
            params.put("pn",pn);
            String result="";
            try {
                result= HttpUtils.requestGet(BaiduFinal.URL,headers,params).replaceAll("(\r\n|\r|\n|\n\r)","");
//                logger.info("result={}",result);
                Document htmlDocument = Jsoup.parse(result);
                Elements elements=htmlDocument.select("h3[class='t']");
                for(Element element:elements){
//                    logger.info("element.toString={}",element.toString());
                    Element titleElement=element.getElementsByTag("a").first();
                    String href=titleElement.attr("href");
                    String title=HtmlUtil.cleanHtmlTag(titleElement.text()).trim();
                    boolean flag=checkCityExist(title,keys);
                    if(flag){
                        SearchResultModel model=new SearchResultModel();
                        model.setK1(keys);
                        model.setPage(pn);
                        model.setTitle(title);
                        model.setUrl(href);
                        datas.add(model);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(!StringUtils.hasText(result)){
                logger.info("搜索结果为空");
                continue;
            }
            try{
                Thread.sleep(50);
            }catch(InterruptedException ie){
            }

        }
        return datas;
    }
    public void writeToFile(List<SearchResultModel> results,String destFile){
        File file=new File(destFile);
        BufferedWriter writer =null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destFile), StandardCharsets.UTF_8));
            for (SearchResultModel data : results) {
                writer.write(data.toString());
                writer.newLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 查找同时存在的值
     * @param key
     * @param latch
     * @return
     */
    public List<SearchResultModel> analyse(String key, CountDownLatch latch) {
        List<SearchResultModel> datas=analyseOne(key);
        if(datas.size()!=0){
            logger.info("key={},size={}",key,datas.size());
        }
        latch.countDown();
        return datas;
    }

    @Override
    public List<SearchResultModel> filterLibrarys(List<SearchResultModel> datas, Map<String, String> librarys) {
        List<SearchResultModel> results=new ArrayList<>();
        for(SearchResultModel data:datas){
            for(Map.Entry<String,String> library:librarys.entrySet()){
                String title=data.getTitle();
                if(title.indexOf(library.getKey())!=-1){
                    results.add(data);
                }
            }
        }
        return results;
    }
    public void writeToFile(String path,String destFile){
        File dir=new File(path);
        File[] files=dir.listFiles();
        List<String> datas=new ArrayList<>();
        String line=null;
        for(File file:files){
            if(file.length()==0){
                logger.info("file.getName={},size={}",file.getName(),file.length());
                continue;
            }
            BufferedReader reader=null;
            String fileName=file.getName();
            fileName=fileName.substring(fileName.indexOf("-")+1,fileName.indexOf(".")+1);
            datas.add("============================="+fileName+"====================================");
            try {
                reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),StandardCharsets.UTF_8));
                while((line=reader.readLine())!=null){
                    datas.add(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(reader!=null){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        BufferedWriter writer =null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destFile), StandardCharsets.UTF_8));
            for (String data : datas) {
                writer.write(data);
                writer.newLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(writer!=null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        SearchKeysServiceImpl service=new SearchKeysServiceImpl();
        long start=System.currentTimeMillis();
//        List<String> keys=service.getKeys();
//        CountDownLatch latch=new CountDownLatch(keys.size());
//        for(String key:keys){
//            new Thread(()->{
//                String destFile="D:/library/library3/result/reults-{key}.txt";
//                List<SearchResultModel> results= service.analyse(key,latch);
//                logger.info("key={},total.size={}",key,results.size());
//                destFile=destFile.replaceAll("\\{key\\}",key);
//                service.writeToFile(results,destFile);
//            }).start();
//        }
//        try {
//            latch.await();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        //--------------------------------------------------
//        Map<String,String> librarys=service.getLibrarys("D:/library/library3/librarys.txt");
//        logger.info("librarys.size=={}",librarys);
//        List<String> keys=service.getKeys();
//        CountDownLatch latch=new CountDownLatch(keys.size());
//        for(String key:keys){
//            new Thread(()->{
//                String destFile="D:/library/library3/result2/reults-{key}.txt";
//                List<SearchResultModel> results= service.analyse(key,latch);
//                List<SearchResultModel> filterResults=service.filterLibrarys(results,librarys);
//                logger.info("key={},total.size={},filter.size={}",key,results.size(),filterResults.size());
//                destFile=destFile.replaceAll("\\{key\\}",key);
//                service.writeToFile(filterResults,destFile);
//            }).start();
//        }
//        try {
//            latch.await();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//



        //--------------------------------------------
        // 根据图书馆+关键词来进行匹配查找对应的数据
        //---------------------------------------------
        String path="D:/library/library3/result2/";
        Map<String,String> librarys=service.getLibrarys(path.replaceAll("/result2/","")+"/librarys119.txt");
        logger.info("librarys.size={}",librarys.size());
        List<String> keys=new ArrayList<>();
        keys.add("扫码借书");
        keys.add("手机借书");
        keys.add("图书转借");
        keys.add("文献转借");
        keys.add("转借");
        keys.add("送书上门");
        keys.add("快递到家");
        keys.add("网借");
        keys.add("网上借阅");
        keys.add("图书共享");
        List<String> resultKeys=service.getKeysFromLibrarys(librarys,keys);//TODO
//        List<String> resultKeys= Arrays.asList("首都图书馆,借书");//TODO

        logger.info("totalKeys={}",resultKeys.size());
        CountDownLatch latch=new CountDownLatch(resultKeys.size());
        ExecutorService executorService= Executors.newFixedThreadPool(5);//TODO
        AtomicInteger indexAtomic=new AtomicInteger(0);
        AtomicInteger finishedAtomic=new AtomicInteger(0);
        int per=BaiduFinal.PER;
        for(String key:resultKeys){
            Thread t=new Thread(()->{
                if(indexAtomic.incrementAndGet()%per==0)logger.info("开始执行第{}个",indexAtomic.get());
                String destFile=path+"/reults-{key}.txt";
                List<SearchResultModel> results= service.analyse(key,latch);
                if(results.size()!=0){
                    logger.info("key={},total.size={}",key,results.size());
                    destFile=destFile.replaceAll("\\{key\\}",key);
                    service.writeToFile(results,destFile);
                }
                if(finishedAtomic.incrementAndGet()%per==0)logger.info("已经执行完成第{}个",finishedAtomic.get());
            });
            executorService.execute(t);
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
        String destFile=path+"/result-total.txt";
        logger.info("path={}",path);
        service.writeToFile(path,destFile);
        long end=System.currentTimeMillis();
        System.out.println("总共花费时间:"+(end-start)/1000+"秒");
        logger.info("ffff");
    }
}
